/**
 * 甘特图性能监控器
 * 监控渲染性能、内存使用、交互响应时间等关键指标
 */

import { ganttErrorHandler, ErrorType } from './ErrorHandler';

export interface PerformanceMetrics {
  renderTime: number;
  frameRate: number;
  memoryUsage: number;
  interactionLatency: number;
  dataProcessingTime: number;
  canvasOperations: number;
  timestamp: number;
}

export interface PerformanceThresholds {
  maxRenderTime: number; // 最大渲染时间 (ms)
  minFrameRate: number; // 最小帧率 (fps)
  maxMemoryUsage: number; // 最大内存使用 (MB)
  maxInteractionLatency: number; // 最大交互延迟 (ms)
  maxDataProcessingTime: number; // 最大数据处理时间 (ms)
}

export interface OptimizationStrategy {
  enableVirtualization: boolean;
  enableCaching: boolean;
  reduceRenderQuality: boolean;
  enableDebouncing: boolean;
  enableLazyLoading: boolean;
}

class PerformanceMonitor {
  private metrics: PerformanceMetrics[] = [];
  private maxMetricsHistory = 1000;
  private isMonitoring = false;
  private monitoringInterval: number | null = null;
  private frameCount = 0;
  private lastFrameTime = 0;
  private renderStartTime = 0;
  private interactionStartTime = 0;
  private dataProcessingStartTime = 0;

  private thresholds: PerformanceThresholds = {
    maxRenderTime: 16, // 60fps = 16ms per frame
    minFrameRate: 30,
    maxMemoryUsage: 100, // 100MB
    maxInteractionLatency: 100, // 100ms
    maxDataProcessingTime: 50, // 50ms
  };

  private currentStrategy: OptimizationStrategy = {
    enableVirtualization: false,
    enableCaching: true,
    reduceRenderQuality: false,
    enableDebouncing: true,
    enableLazyLoading: false,
  };

  // 开始监控
  startMonitoring(interval: number = 1000) {
    if (this.isMonitoring) {
      return;
    }

    this.isMonitoring = true;
    this.monitoringInterval = window.setInterval(() => {
      this.collectMetrics();
      this.analyzePerformance();
    }, interval);

    console.log('性能监控已启动');
  }

  // 停止监控
  stopMonitoring() {
    if (!this.isMonitoring) {
      return;
    }

    this.isMonitoring = false;
    if (this.monitoringInterval) {
      clearInterval(this.monitoringInterval);
      this.monitoringInterval = null;
    }

    console.log('性能监控已停止');
  }

  // 开始渲染计时
  startRenderTimer(): number {
    this.renderStartTime = performance.now();
    return this.renderStartTime;
  }

  // 结束渲染计时
  endRenderTimer(startTime?: number): number {
    const endTime = performance.now();
    const renderTime = endTime - (startTime || this.renderStartTime);

    // 检查渲染时间是否超过阈值
    if (renderTime > this.thresholds.maxRenderTime) {
      ganttErrorHandler.logError(
        ErrorType.PERFORMANCE_ERROR,
        `渲染时间过长: ${renderTime.toFixed(2)}ms (阈值: ${this.thresholds.maxRenderTime}ms)`,
        undefined,
        { renderTime, threshold: this.thresholds.maxRenderTime },
        'medium'
      );

      this.triggerOptimization('render');
    }

    return renderTime;
  }

  // 开始交互计时
  startInteractionTimer() {
    this.interactionStartTime = performance.now();
  }

  // 结束交互计时
  endInteractionTimer(): number {
    const endTime = performance.now();
    const latency = endTime - this.interactionStartTime;

    // 检查交互延迟是否超过阈值
    if (latency > this.thresholds.maxInteractionLatency) {
      ganttErrorHandler.logError(
        ErrorType.PERFORMANCE_ERROR,
        `交互延迟过高: ${latency.toFixed(2)}ms (阈值: ${this.thresholds.maxInteractionLatency}ms)`,
        undefined,
        { latency, threshold: this.thresholds.maxInteractionLatency },
        'medium'
      );
    }

    return latency;
  }

  // 开始数据处理计时
  startDataProcessingTimer() {
    this.dataProcessingStartTime = performance.now();
  }

  // 结束数据处理计时
  endDataProcessingTimer(): number {
    const endTime = performance.now();
    const processingTime = endTime - this.dataProcessingStartTime;

    // 检查数据处理时间是否超过阈值
    if (processingTime > this.thresholds.maxDataProcessingTime) {
      ganttErrorHandler.logError(
        ErrorType.PERFORMANCE_ERROR,
        `数据处理时间过长: ${processingTime.toFixed(2)}ms (阈值: ${this.thresholds.maxDataProcessingTime}ms)`,
        undefined,
        { processingTime, threshold: this.thresholds.maxDataProcessingTime },
        'medium'
      );
    }

    return processingTime;
  }

  // 收集性能指标
  private collectMetrics() {
    const now = performance.now();

    // 计算帧率
    this.frameCount++;
    if (now - this.lastFrameTime >= 1000) {
      const frameRate = this.frameCount;
      this.frameCount = 0;
      this.lastFrameTime = now;

      // 获取内存使用情况
      const memoryUsage = this.getMemoryUsage();

      const metrics: PerformanceMetrics = {
        renderTime: 0, // 将在渲染时更新
        frameRate,
        memoryUsage,
        interactionLatency: 0, // 将在交互时更新
        dataProcessingTime: 0, // 将在数据处理时更新
        canvasOperations: 0, // 将在Canvas操作时更新
        timestamp: now,
      };

      this.addMetrics(metrics);
    }
  }

  // 添加性能指标
  private addMetrics(metrics: PerformanceMetrics) {
    this.metrics.unshift(metrics);
    if (this.metrics.length > this.maxMetricsHistory) {
      this.metrics.pop();
    }
  }

  // 分析性能
  private analyzePerformance() {
    if (this.metrics.length === 0) return;

    const recent = this.metrics.slice(0, 10);
    const avgFrameRate =
      recent.reduce((sum, m) => sum + m.frameRate, 0) / recent.length;
    const avgMemoryUsage =
      recent.reduce((sum, m) => sum + m.memoryUsage, 0) / recent.length;

    // 检查帧率
    if (avgFrameRate < this.thresholds.minFrameRate) {
      ganttErrorHandler.logError(
        ErrorType.PERFORMANCE_ERROR,
        `帧率过低: ${avgFrameRate.toFixed(1)}fps (阈值: ${this.thresholds.minFrameRate}fps)`,
        undefined,
        { frameRate: avgFrameRate, threshold: this.thresholds.minFrameRate },
        'medium'
      );

      this.triggerOptimization('framerate');
    }

    // 检查内存使用
    if (avgMemoryUsage > this.thresholds.maxMemoryUsage) {
      ganttErrorHandler.logError(
        ErrorType.MEMORY_ERROR,
        `内存使用过高: ${avgMemoryUsage.toFixed(1)}MB (阈值: ${this.thresholds.maxMemoryUsage}MB)`,
        undefined,
        {
          memoryUsage: avgMemoryUsage,
          threshold: this.thresholds.maxMemoryUsage,
        },
        'high'
      );

      this.triggerOptimization('memory');
    }
  }

  // 触发优化策略
  private triggerOptimization(
    type: 'render' | 'framerate' | 'memory' | 'interaction'
  ) {
    switch (type) {
      case 'render':
        if (!this.currentStrategy.enableVirtualization) {
          this.currentStrategy.enableVirtualization = true;
          console.log('启用虚拟化渲染以提高性能');
        }
        if (!this.currentStrategy.reduceRenderQuality) {
          this.currentStrategy.reduceRenderQuality = true;
          console.log('降低渲染质量以提高性能');
        }
        break;

      case 'framerate':
        if (!this.currentStrategy.enableDebouncing) {
          this.currentStrategy.enableDebouncing = true;
          console.log('启用防抖以提高帧率');
        }
        break;

      case 'memory':
        if (!this.currentStrategy.enableLazyLoading) {
          this.currentStrategy.enableLazyLoading = true;
          console.log('启用懒加载以减少内存使用');
        }
        // 触发垃圾回收
        this.forceGarbageCollection();
        break;

      case 'interaction':
        if (!this.currentStrategy.enableDebouncing) {
          this.currentStrategy.enableDebouncing = true;
          console.log('启用防抖以减少交互延迟');
        }
        break;
    }
  }

  // 获取内存使用情况
  private getMemoryUsage(): number {
    if ('memory' in performance) {
      const memory = (performance as any).memory;
      return memory.usedJSHeapSize / 1024 / 1024; // 转换为 MB
    }
    return 0;
  }

  // 强制垃圾回收
  private forceGarbageCollection() {
    if ('gc' in window) {
      (window as any).gc();
      console.log('已触发垃圾回收');
    }
  }

  // 获取性能统计
  getPerformanceStats() {
    if (this.metrics.length === 0) {
      return null;
    }

    const recent = this.metrics.slice(0, 100);
    const stats = {
      avgRenderTime:
        recent.reduce((sum, m) => sum + m.renderTime, 0) / recent.length,
      avgFrameRate:
        recent.reduce((sum, m) => sum + m.frameRate, 0) / recent.length,
      avgMemoryUsage:
        recent.reduce((sum, m) => sum + m.memoryUsage, 0) / recent.length,
      avgInteractionLatency:
        recent.reduce((sum, m) => sum + m.interactionLatency, 0) /
        recent.length,
      avgDataProcessingTime:
        recent.reduce((sum, m) => sum + m.dataProcessingTime, 0) /
        recent.length,
      totalMetrics: this.metrics.length,
      currentStrategy: { ...this.currentStrategy },
      thresholds: { ...this.thresholds },
    };

    return stats;
  }

  // 获取性能报告
  getPerformanceReport() {
    const stats = this.getPerformanceStats();
    if (!stats) {
      return '暂无性能数据';
    }

    return `
甘特图性能报告:
================
平均渲染时间: ${stats.avgRenderTime.toFixed(2)}ms
平均帧率: ${stats.avgFrameRate.toFixed(1)}fps
平均内存使用: ${stats.avgMemoryUsage.toFixed(1)}MB
平均交互延迟: ${stats.avgInteractionLatency.toFixed(2)}ms
平均数据处理时间: ${stats.avgDataProcessingTime.toFixed(2)}ms

当前优化策略:
- 虚拟化渲染: ${stats.currentStrategy.enableVirtualization ? '启用' : '禁用'}
- 缓存: ${stats.currentStrategy.enableCaching ? '启用' : '禁用'}
- 降低渲染质量: ${stats.currentStrategy.reduceRenderQuality ? '启用' : '禁用'}
- 防抖: ${stats.currentStrategy.enableDebouncing ? '启用' : '禁用'}
- 懒加载: ${stats.currentStrategy.enableLazyLoading ? '启用' : '禁用'}

性能阈值:
- 最大渲染时间: ${stats.thresholds.maxRenderTime}ms
- 最小帧率: ${stats.thresholds.minFrameRate}fps
- 最大内存使用: ${stats.thresholds.maxMemoryUsage}MB
- 最大交互延迟: ${stats.thresholds.maxInteractionLatency}ms
    `.trim();
  }

  // 设置性能阈值
  setThresholds(thresholds: Partial<PerformanceThresholds>) {
    this.thresholds = { ...this.thresholds, ...thresholds };
  }

  // 获取当前优化策略
  getCurrentStrategy(): OptimizationStrategy {
    return { ...this.currentStrategy };
  }

  // 设置优化策略
  setOptimizationStrategy(strategy: Partial<OptimizationStrategy>) {
    this.currentStrategy = { ...this.currentStrategy, ...strategy };
  }

  // 清理性能数据
  clearMetrics() {
    this.metrics = [];
    this.frameCount = 0;
    this.lastFrameTime = 0;
  }

  // 导出性能数据
  exportMetrics() {
    return {
      metrics: [...this.metrics],
      thresholds: { ...this.thresholds },
      strategy: { ...this.currentStrategy },
      timestamp: Date.now(),
    };
  }
}

// 创建全局性能监控器实例
export const performanceMonitor = new PerformanceMonitor();

// 性能监控装饰器
export function monitorPerformance(type: 'render' | 'interaction' | 'data') {
  return function (
    _target: any,
    _propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;

    descriptor.value = function (...args: any[]) {
      let startTimer: () => void;
      let endTimer: () => number;

      switch (type) {
        case 'render':
          startTimer = () => performanceMonitor.startRenderTimer();
          endTimer = () => performanceMonitor.endRenderTimer();
          break;
        case 'interaction':
          startTimer = () => performanceMonitor.startInteractionTimer();
          endTimer = () => performanceMonitor.endInteractionTimer();
          break;
        case 'data':
          startTimer = () => performanceMonitor.startDataProcessingTimer();
          endTimer = () => performanceMonitor.endDataProcessingTimer();
          break;
        default:
          return originalMethod.apply(this, args);
      }

      startTimer();
      try {
        const result = originalMethod.apply(this, args);

        // 处理异步方法
        if (result instanceof Promise) {
          return result.finally(() => {
            endTimer();
          });
        }

        endTimer();
        return result;
      } catch (error) {
        endTimer();
        throw error;
      }
    };

    return descriptor;
  };
}

// 导出工具函数
export const performanceUtils = {
  startRenderTimer: () => performanceMonitor.startRenderTimer(),
  endRenderTimer: (startTime?: number) =>
    performanceMonitor.endRenderTimer(startTime),
  startInteractionTimer: () => performanceMonitor.startInteractionTimer(),
  endInteractionTimer: () => performanceMonitor.endInteractionTimer(),
  startDataProcessingTimer: () => performanceMonitor.startDataProcessingTimer(),
  endDataProcessingTimer: () => performanceMonitor.endDataProcessingTimer(),
  getStats: () => performanceMonitor.getPerformanceStats(),
  getReport: () => performanceMonitor.getPerformanceReport(),
};
